package com.example.http

import android.os.Environment
import android.util.Log
import com.alibaba.android.arouter.launcher.ARouter
import com.example.base.app.BaseConst
import com.example.base.app.RouterPath
import com.tencent.mmkv.MMKV
import okhttp3.Cache
import okhttp3.Interceptor
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient
import okhttp3.Protocol
import okhttp3.Response
import okhttp3.ResponseBody.Companion.toResponseBody
import okhttp3.logging.HttpLoggingInterceptor
import org.json.JSONObject
import java.io.File
import java.net.Proxy
import java.security.SecureRandom
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLHandshakeException
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager

/**
 * Author: Jason Zhang
 * Date: 2025/8/19
 * Desc: 获取OKHttpClient实例
 */
object ClientManager {

    /**
     * 获取普通客户端
     * 支持Http
     */
    fun createCommonOkHttpClient(): OkHttpClient{
        val okBuilder = OkHttpClient.Builder() //建造者设计模式
        okBuilder.apply {
            //连接超时
            connectTimeout(10, TimeUnit.SECONDS)
            //读超时
            readTimeout(10, TimeUnit.SECONDS)
            //写超时
            writeTimeout(10, TimeUnit.SECONDS)

            //设置日志拦截器（避免线上环境给系统输出日志）
            if (BuildConfig.isOpenLog){ //BuildConfig文件是在构建中生成
                addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
            }
        }
        return okBuilder.build()
    }

    /**
     * 获取带Token的客户端
     * 支持Http
     */
    fun createTokenOkHttpClient(): OkHttpClient{
        val okBuilder = OkHttpClient.Builder() //建造者设计模式
        okBuilder.apply {
            //连接超时
            connectTimeout(10, TimeUnit.SECONDS)
            //读超时
            readTimeout(10, TimeUnit.SECONDS)
            //写超时
            writeTimeout(10, TimeUnit.SECONDS)

            //设置日志拦截器（避免线上环境给系统输出日志）
            if (BuildConfig.isOpenLog){ //BuildConfig文件是在构建中生成
                addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
            }

            //Token拦截器
            addInterceptor(getTokenInterceptor())

        }
        return okBuilder.build()
    }

    /**
     * 获取普通客户端
     * 支持Https
     */
    fun createCommonOkHttpsClient(): OkHttpClient{
        val okBuilder = OkHttpClient.Builder() //建造者设计模式
        okBuilder.apply {
            //连接超时
            connectTimeout(10, TimeUnit.SECONDS)
            //读超时
            readTimeout(10, TimeUnit.SECONDS)
            //写超时
            writeTimeout(10, TimeUnit.SECONDS)

            //设置日志拦截器（避免线上环境给系统输出日志）
            if (BuildConfig.isOpenLog){ //BuildConfig文件是在构建中生成
                addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
            }

            //服务器异常拦截器
            addInterceptor(getServiceInterceptor())

            //如果要支持Https请求，支持加密传输（对称和非对称加密都可以）
            sslSocketFactory(sslSocketFactory, trustManager)

            //防止使用网络代理，抓包接口
            proxy(Proxy.NO_PROXY)
            //设置Http网络协议版本，Http1.0，Http2.0和Http3.0（QUIC）
            protocols(listOf(Protocol.HTTP_2))

            //设置网络缓存（默认没有网络缓存）
            val externalDirPath = Environment.getExternalStorageDirectory().absolutePath
            if (externalDirPath.isNotEmpty()){
                cache(Cache(File("${externalDirPath}/videoCache"), 10 * 1024 * 1024)) //10M
            }

        }
        return okBuilder.build()

    }

    /**
     * 获取普通客户端
     * 支持Https
     */
    fun createTokenOkHttpsClient(): OkHttpClient{
        val okBuilder = OkHttpClient.Builder() //建造者设计模式
        okBuilder.apply {
            //连接超时
            connectTimeout(10, TimeUnit.SECONDS)
            //读超时
            readTimeout(10, TimeUnit.SECONDS)
            //写超时
            writeTimeout(10, TimeUnit.SECONDS)

            //设置日志拦截器（避免线上环境给系统输出日志）
            if (BuildConfig.isOpenLog){ //BuildConfig文件是在构建中生成
                addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
            }

            //Header头拦截器
            addInterceptor(getTokenInterceptor())

            //服务器异常拦截器
            addInterceptor(getServiceInterceptor())

            //如果要支持Https请求，支持加密传输（对称和非对称加密都可以）
            sslSocketFactory(sslSocketFactory, trustManager)

            //防止使用网络代理，抓包接口
            proxy(Proxy.NO_PROXY)
            //设置Http网络协议版本，Http1.0，Http2.0和Http3.0（QUIC）
            protocols(listOf(Protocol.HTTP_2))

            //设置网络缓存（默认没有网络缓存）
            val externalDirPath = Environment.getExternalStorageDirectory().absolutePath
            if (externalDirPath.isNotEmpty()){
                cache(Cache(File("${externalDirPath}/videoCache"), 10 * 1024 * 1024)) //10M
            }

        }
        return okBuilder.build()

    }

    private val sslSocketFactory: SSLSocketFactory
        get() = try {
            val sslContent = SSLContext.getInstance("SSL")
            sslContent.init(null, arrayOf(), SecureRandom())
            sslContent.socketFactory
        }catch (e: Exception){
            throw RuntimeException(e.message)
        }

    private val trustManager: X509TrustManager
        get() = object : X509TrustManager{
            /**
             * 校验客户端证书
             */
            override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {

            }

            /**
             * 校验服务端证书
             */
            override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {
                //防止抓包，如：Fiddler, Charless抓包工具
                chain?.forEach {
                    if (it.issuerX500Principal.name.contains("Charles") ||
                        it.issuerX500Principal.name.contains("Fiddler")){
                        throw SSLHandshakeException("当前应用不让代理抓包，请放弃抓包行为！")
                    }
                }
            }

            /**
             * 获取可以被接收端
             */
            override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
        }


    /**
     * Token拦截器
     * 设计模式：责任链模式
     */
    private fun getTokenInterceptor(): Interceptor{
        return Interceptor { chain ->
            val token = MMKV.defaultMMKV().decodeString("token", "").toString()
            //从请求链上获取请求建造者对象
            var newRequestBuilder = chain.request().newBuilder()
            newRequestBuilder.header("token", token)


            //生成新的请求对象
            var newRequest = newRequestBuilder.build()

            //执行请求获取返回结果
            var response = chain.proceed(newRequest)

            //校验一下Token是否过期
            if (response.code == 403 || response.code == 401){
                ARouter.getInstance().build(RouterPath.PATH_LOGIN_PAGE).navigation()
            }

            response
        }
    }


    /**
     * 服务器返回拦截器
     */
    private fun getServiceInterceptor(): Interceptor{
        return Interceptor { chain -> ///执行请求获取返回
            var response = chain.proceed(chain.request())
            var responseBuilder = response.newBuilder()
            //代表服务器接口报错
            if (response.code == 500){
                var errorJson = JSONObject().apply {
                    put("code", 500)
                    put("message", "服务器异常，请联系客服！")
                }
                responseBuilder.body(errorJson.toString().toResponseBody("application/json;charset=UTF-8".toMediaTypeOrNull()))
            }
            responseBuilder.build()
        }
    }


}